package org.jeecg.modules.wms.controller;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.wms.entity.WmsOutbound;
import org.jeecg.modules.wms.entity.WmsOutboundAllocationPlan;
import org.jeecg.modules.wms.service.IWmsOutboundService;
import org.jeecg.modules.wms.service.IWmsOutboundAllocationPlanService;
import org.jeecg.modules.wms.vo.WmsOutboundVO;
import org.jeecg.modules.wms.vo.OutboundAllocationResult;
import org.jeecg.modules.wms.vo.OneClickOutboundRequest;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

/**
 * @Description: 出库单管理
 * @Author: jeecg-boot
 * @Date: 2023-07-01
 * @Version: V1.0
 */
@Api(tags = "出库单管理")
@RestController
@RequestMapping("/wms/outbound")
@Slf4j
public class WmsOutboundController extends JeecgController<WmsOutbound, IWmsOutboundService> {
    @Autowired
    private IWmsOutboundService wmsOutboundService;

    @Autowired
    private IWmsOutboundAllocationPlanService wmsOutboundAllocationPlanService;

    /**
     * 分页列表查询
     *
     * @param wmsOutbound 查询条件
     * @param pageNo      页码
     * @param pageSize    每页条数
     * @param req         请求
     * @return 分页数据
     */
    @AutoLog(value = "出库单-分页列表查询")
    @ApiOperation(value = "出库单-分页列表查询", notes = "出库单-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(WmsOutbound wmsOutbound,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        Page<WmsOutboundVO> page = new Page<>(pageNo, pageSize);
        IPage<WmsOutboundVO> pageList = wmsOutboundService.queryOutboundList(page, wmsOutbound);
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param wmsOutboundVO 出库单信息
     * @return 操作结果
     */
    @AutoLog(value = "出库单-添加")
    @ApiOperation(value = "出库单-添加", notes = "出库单-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody WmsOutboundVO wmsOutboundVO) {
        boolean result = wmsOutboundService.add(wmsOutboundVO);
        if (result) {
            return Result.OK("添加成功！", wmsOutboundVO.getId());
        }
        return Result.error("添加失败！");
    }

    /**
     * 编辑
     *
     * @param wmsOutboundVO 出库单信息
     * @return 操作结果
     */
    @AutoLog(value = "出库单-编辑")
    @ApiOperation(value = "出库单-编辑", notes = "出库单-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody WmsOutboundVO wmsOutboundVO) {
        boolean result = wmsOutboundService.edit(wmsOutboundVO);
        if (result) {
            return Result.OK("编辑成功！");
        }
        return Result.error("编辑失败！");
    }

    /**
     * 通过id删除
     *
     * @param id 出库单ID
     * @return 操作结果
     */
    @AutoLog(value = "出库单-通过id删除")
    @ApiOperation(value = "出库单-通过id删除", notes = "出库单-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id") String id) {
        boolean result = wmsOutboundService.delete(id);
        if (result) {
            return Result.OK("删除成功！");
        }
        return Result.error("删除失败！");
    }

    /**
     * 批量删除
     *
     * @param ids 出库单ID数组
     * @return 操作结果
     */
    @AutoLog(value = "出库单-批量删除")
    @ApiOperation(value = "出库单-批量删除", notes = "出库单-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids") String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不能为空！");
        }
        String[] idArr = ids.split(",");
        for (String id : idArr) {
            wmsOutboundService.delete(id);
        }
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id 出库单ID
     * @return 出库单详情
     */
    @AutoLog(value = "出库单-通过id查询")
    @ApiOperation(value = "出库单-通过id查询", notes = "出库单-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id") String id) {
        WmsOutboundVO wmsOutboundVO = wmsOutboundService.queryById(id);
        if (wmsOutboundVO == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(wmsOutboundVO);
    }

    /**
     * 查询出库单详情（移动端专用）
     *
     * @param id 出库单ID
     * @return 出库单详情包含明细和分配计划
     */
    @AutoLog(value = "出库单-查询详情")
    @ApiOperation(value = "出库单-查询详情", notes = "出库单-查询详情（移动端）")
    @GetMapping(value = "/detail/{id}")
    public Result<?> getDetail(@PathVariable("id") String id) {
        try {
            WmsOutboundVO wmsOutboundVO = wmsOutboundService.queryById(id);
            if (wmsOutboundVO == null) {
                return Result.error("未找到对应数据");
            }

            // 查询分配计划
            List<WmsOutboundAllocationPlan> allocationPlans = wmsOutboundAllocationPlanService.getByOutboundId(id);

            // 构建返回数据
            Map<String, Object> result = new HashMap<>();
            result.put("outbound", wmsOutboundVO);
            result.put("details", wmsOutboundVO.getOutboundDetailList());
            result.put("allocationPlans", allocationPlans);

            return Result.OK(result);
        } catch (Exception e) {
            log.error("查询出库单详情失败", e);
            return Result.error("查询详情失败：" + e.getMessage());
        }
    }

    /**
     * 取消出库单
     *
     * @param id 出库单ID
     * @return 操作结果
     */
    @AutoLog(value = "出库单-取消")
    @ApiOperation(value = "出库单-取消", notes = "出库单-取消")
    @PutMapping(value = "/cancel")
    public Result<?> cancel(@RequestParam(name = "id") String id) {
        boolean result = wmsOutboundService.cancel(id);
        if (result) {
            return Result.OK("取消成功！");
        }
        return Result.error("取消失败！");
    }

    /**
     * 审核出库单
     *
     * @param id     出库单ID
     * @param isPass 是否通过
     * @param remark 审核意见
     * @return 操作结果
     */
    @AutoLog(value = "出库单-审核")
    @ApiOperation(value = "出库单-审核", notes = "出库单-审核")
    @PutMapping(value = "/audit")
    public Result<?> audit(@RequestParam(name = "id") String id,
                           @RequestParam(name = "isPass") boolean isPass,
                           @RequestParam(name = "remark", required = false) String remark) {
        try {
            boolean result = wmsOutboundService.audit(id, isPass, remark);
            if (result && isPass) {
                // 审核通过后自动生成预出库分配方案
                OutboundAllocationResult allocationResult = wmsOutboundAllocationPlanService.autoAllocateOutbound(id);

                // 返回审核结果和分配方案
                Map<String, Object> responseData = new HashMap<>();
                responseData.put("auditSuccess", true);
                responseData.put("allocationResult", allocationResult);

                if (allocationResult.isSuccess()) {
                    if (allocationResult.isFullySatisfied()) {
                        return Result.OK("审核成功！库存充足，已完成预出库分配", responseData);
                    } else {
                        return Result.OK("审核成功！但部分物料库存不足，请查看分配方案", responseData);
                    }
                } else {
                    return Result.OK("审核成功！但分配方案生成失败：" + allocationResult.getMessage(), responseData);
                }
            } else if (result) {
                return Result.OK("审核成功！");
            } else {
                return Result.error("审核失败！");
            }
        } catch (Exception e) {
            log.error("审核出库单失败", e);
            return Result.error("审核失败：" + e.getMessage());
        }
    }

    /**
     * 执行出库
     *
     * @param id 出库单ID
     * @return 操作结果
     */
    @AutoLog(value = "出库单-执行出库")
    @ApiOperation(value = "出库单-执行出库", notes = "出库单-执行出库")
    @PutMapping(value = "/execute")
    public Result<?> execute(@RequestParam(name = "id") String id) {
        boolean result = wmsOutboundService.execute(id);
        if (result) {
            return Result.OK("出库成功！");
        }
        return Result.error("出库失败！");
    }

    /**
     * 导出excel
     *
     * @param request     请求
     * @param wmsOutbound 查询条件
     */
    @AutoLog(value = "出库单-导出")
    @ApiOperation(value = "出库单-导出", notes = "出库单-导出")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, WmsOutbound wmsOutbound) {
        return super.exportXls(request, wmsOutbound, WmsOutbound.class, "出库单");
    }

    /**
     * 通过excel导入数据
     *
     * @param request  请求
     * @param response 响应
     * @return 操作结果
     */
    @AutoLog(value = "出库单-导入")
    @ApiOperation(value = "出库单-导入", notes = "出库单-导入")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, WmsOutbound.class);
    }

    /**
     * 上传出库凭证
     *
     * @param request 请求
     * @return 操作结果
     */
    @AutoLog(value = "出库单-上传凭证")
    @ApiOperation(value = "出库单-上传凭证", notes = "出库单-上传凭证")
    @PostMapping(value = "/uploadVoucher")
    public Result<?> uploadVoucher(HttpServletRequest request) {
        String id = request.getParameter("id");
        if (id == null || "".equals(id.trim())) {
            return Result.error("参数不能为空！");
        }

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        if (file == null) {
            return Result.error("未找到上传文件！");
        }

        boolean result = wmsOutboundService.uploadVoucher(id, file);
        if (result) {
            return Result.OK("上传成功！");
        }
        return Result.error("上传失败！");
    }

    /**
     * 打印出库单
     *
     * @param id 出库单ID
     * @return 打印数据
     */
    @AutoLog(value = "出库单-打印")
    @ApiOperation(value = "出库单-打印", notes = "出库单-打印")
    @GetMapping(value = "/print")
    public Result<?> print(@RequestParam(name = "id") String id) {
        WmsOutboundVO wmsOutboundVO = wmsOutboundService.queryById(id);
        if (wmsOutboundVO == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(wmsOutboundVO);
    }

    /**
     * 查询出库分配方案
     *
     * @param outboundId 出库单ID
     * @return 分配方案列表
     */
    @AutoLog(value = "出库单-查询分配方案")
    @ApiOperation(value = "出库单-查询分配方案", notes = "出库单-查询分配方案")
    @GetMapping(value = "/getAllocationPlan")
    public Result<?> getAllocationPlan(@RequestParam(name = "outboundId") String outboundId) {
        try {
            List<WmsOutboundAllocationPlan> allocationPlans = wmsOutboundAllocationPlanService.getByOutboundId(outboundId);
            return Result.OK(allocationPlans);
        } catch (Exception e) {
            log.error("查询出库分配方案失败", e);
            return Result.error("查询分配方案失败：" + e.getMessage());
        }
    }

    /**
     * 手动重新分配出库方案
     *
     * @param outboundId 出库单ID
     * @return 分配结果
     */
    @AutoLog(value = "出库单-重新分配方案")
    @ApiOperation(value = "出库单-重新分配方案", notes = "出库单-重新分配方案")
    @PostMapping(value = "/reallocate")
    public Result<?> reallocate(@RequestParam(name = "outboundId") String outboundId) {
        try {
            OutboundAllocationResult result = wmsOutboundAllocationPlanService.autoAllocateOutbound(outboundId);
            if (result.isSuccess()) {
                return Result.OK(result);
            } else {
                return Result.error(result.getMessage());
            }
        } catch (Exception e) {
            log.error("重新分配出库方案失败", e);
            return Result.error("重新分配失败：" + e.getMessage());
        }
    }

    /**
     * 一键出库
     *
     * @param id 出库单ID
     * @return 操作结果
     */
    @AutoLog(value = "出库单-一键出库")
    @ApiOperation(value = "出库单-一键出库", notes = "出库单-一键出库")
    @PutMapping(value = "/oneClickOutbound")
    public Result<?> oneClickOutbound(@RequestParam(name = "id") String id) {
        try {
            boolean result = wmsOutboundService.oneClickOutbound(id);
            if (result) {
                return Result.OK("一键出库成功！");
            } else {
                return Result.error("一键出库失败！");
            }
        } catch (Exception e) {
            log.error("一键出库失败", e);
            return Result.error("一键出库失败：" + e.getMessage());
        }
    }

    /**
     * 一键出库
     *
     * @param request 请求参数
     * @return 操作结果
     */
    @AutoLog(value = "出库单-一键出库")
    @ApiOperation(value = "出库单-一键出库", notes = "出库单-一键出库")
    @PutMapping(value = "/oneClickOutboundForMobile")
    public Result<?> oneClickOutboundForMobile(@RequestBody OneClickOutboundRequest request) {
        try {
            boolean result = wmsOutboundService.oneClickOutboundForMobile(request.getId(), request.getPlanIdList());
            if (result) {
                return Result.OK("一键出库成功！");
            } else {
                return Result.error("一键出库失败！");
            }
        } catch (Exception e) {
            log.error("一键出库失败", e);
            return Result.error("一键出库失败：" + e.getMessage());
        }
    }

    /**
     * 查询当前用户操作的出库单记录
     *
     * @param pageNo   页码
     * @param pageSize 每页条数
     * @return 操作记录列表
     */
    @AutoLog(value = "出库单-查询用户操作记录")
    @ApiOperation(value = "出库单-查询用户操作记录", notes = "出库单-查询用户操作记录")
    @GetMapping(value = "/getUserOperationRecords")
    public Result<?> getUserOperationRecords(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                             @RequestParam(name = "outboundNo", required = false) String outboundNo,
                                             @RequestParam(name = "status", required = false) String status,
                                             @RequestParam(name = "businessType", required = false) String businessType,
                                             @RequestParam(name = "planOutboundStartTime", required = false) String planOutboundStartTime,
                                             @RequestParam(name = "planOutboundEndTime", required = false) String planOutboundEndTime,
                                             @RequestParam(name = "actualOutboundStartTime", required = false) String actualOutboundStartTime,
                                             @RequestParam(name = "actualOutboundEndTime", required = false) String actualOutboundEndTime,
                                             @RequestParam(name = "warehouseName", required = false) String warehouseName,
                                             @RequestParam(name = "locationName", required = false) String locationName,
                                             @RequestParam(name = "materialCode", required = false) String materialCode,
                                             @RequestParam(name = "materialName", required = false) String materialName) {
        try {
            Page<WmsOutboundVO> page = new Page<>(pageNo, pageSize);

            // 构建查询条件
            WmsOutbound queryParam = new WmsOutbound();
            if (StringUtils.isNotBlank(outboundNo)) {
                queryParam.setOutboundNo(outboundNo);
            }

            IPage<WmsOutboundVO> pageList = wmsOutboundService.getUserOperationRecords(page, queryParam,
                    planOutboundStartTime, planOutboundEndTime, actualOutboundStartTime, actualOutboundEndTime,
                    warehouseName, locationName, materialCode,materialName,
                    (StringUtils.isNotBlank(status) ? Arrays.asList(status.split(",")) : null),
                    (StringUtils.isNotBlank(businessType) ? Arrays.asList(businessType.split(",")) : null));
            return Result.OK(pageList);
        } catch (Exception e) {
            log.error("查询用户出库操作记录失败", e);
            return Result.error("查询操作记录失败：" + e.getMessage());
        }
    }


    /**
     * 解析余料出库单Excel文件
     */
    @AutoLog(value = "出库单管理-解析余料出库单Excel文件")
    @ApiOperation(value = "出库单管理-解析余料出库单Excel文件", notes = "解析上传的Excel文件，提取余料出库单数据")
    @PostMapping(value = "/parseRemainingMaterialFile")
    public Result<List<Map<String, Object>>> parseRemainingMaterialFile(@RequestParam("file") MultipartFile file) {
        try {
            log.info("开始解析余料出库单Excel文件，文件名: {}", file.getOriginalFilename());

            if (file.isEmpty()) {
                return Result.error("上传文件为空");
            }

            // 检查文件类型
            String fileName = file.getOriginalFilename();
            if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
                return Result.error("文件格式不正确，请上传Excel文件");
            }

            // 调用服务层解析Excel文件
            List<Map<String, Object>> parsedData = wmsOutboundService.parseRemainingMaterialExcel(file);

            log.info("Excel文件解析完成，共解析出 {} 条数据", parsedData.size());
            return Result.OK(parsedData);

        } catch (Exception e) {
            log.error("解析余料出库单Excel文件失败", e);
            return Result.error("文件解析失败: " + e.getMessage());
        }
    }

    /**
     * 保存余料出库单导入数据
     */
    @AutoLog(value = "出库单管理-保存余料出库单导入数据")
    @ApiOperation(value = "出库单管理-保存余料出库单导入数据", notes = "保存从Excel导入的余料出库单数据")
    @PostMapping(value = "/saveRemainingMaterialOutbound")
    public Result<?> saveRemainingMaterialOutbound(@RequestBody Map<String, Object> params) {
        try {
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) params.get("dataList");
            if (dataList == null || dataList.isEmpty()) {
                return Result.error("导入数据不能为空");
            }

            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            String createBy = sysUser.getUsername();

            // 调用服务层保存余料出库单数据
            Boolean savedCount = wmsOutboundService.saveRemainingMaterialOutbound(dataList, createBy);

            return Result.OK("导入成功");

        } catch (Exception e) {
            log.error("保存余料出库单导入数据失败", e);
            return Result.error("保存失败: " + e.getMessage());
        }
    }
}